﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using WCFLOBTalk.SalesForceWCF.SFService;

namespace WCFLOBTalk.SalesForceWCF.Helpers
{
    public class SFHelper
    {

        private static SforceService serviceInstance = null;
        static string instanceName = "";

        private static DateTime LastBuilt = DateTime.Now;

        public static bool IsStillValidConnection()
        {
            bool ret = false;

            if (LastBuilt.AddHours(2) > DateTime.Now)
            {
                ret = true;
            }

            return ret;
        }

        private static string ConvertUriToUrl(string uri) {

            // replace the scheme with http
            string newUrl = uri.Replace("salesforcewcf", "https");
            newUrl = newUrl.Split(Convert.ToChar("?")).GetValue(0).ToString();

            return newUrl;
        }

        private static void LogInstanceInfo(string url)
        {
            // parse the instance name
            string instance = url;
            instance = instance.Replace("https://", "");
            string[] urlParts = instance.Split(Convert.ToChar("/"));
            if (urlParts.Length > 0)
            {
                string domain = urlParts[0];
                string[] domainParts = domain.Split(Convert.ToChar("."));
                if (domainParts.Length > 0)
                {
                    string firstPart = domainParts[0];
                    firstPart = firstPart.Replace("-api", "");
                    instanceName = firstPart;
                    System.Diagnostics.Debug.WriteLine(String.Format("instance name: {0}", instanceName));
                }
            }
        }

        public static SforceService Login(string uri, string userName, string password, string securityToken, bool isMetadataUrl, string version)
        {
            
            if (serviceInstance == null || (LastBuilt.AddHours(2) < DateTime.Now))
            {    
                SFService.SforceService c = new SforceService();
                
                //url = url + "/" + version;
                c.Url = ConvertUriToUrl(uri);

                //MessageBox.Show(String.Format("url: {0}, username: {1}, password: {2}, securityToken: {3}, version: {4}", newUrl, userName, password, securityToken, version));

                c.Timeout = 60000;

                LoginResult lr = null;
                // Alternate entry point for calling from .NET
                lr = c.login(userName, password + securityToken);

                //MessageBox.Show("login successful!");
   
                // normally this
                c.Url = lr.serverUrl;
            
                c.SessionHeaderValue = new SessionHeader();
                c.SessionHeaderValue.sessionId = lr.sessionId;
                serviceInstance = c;
                LastBuilt = DateTime.Now;

                LogInstanceInfo(c.Url);

            }

            return serviceInstance;

        }

        

        public static SFMetadata RetrieveMetadata(SforceService connectionInstance) {

            bool IsInternetConnected = true;

            SFMetadata sfm = new SFMetadata();

            if (IsInternetConnected)
            {

                sfm = new SFMetadata();
                List<SFObjectType> types = new List<SFObjectType>();

                // Populate types - .types() not in my web ref. why not?
                string[] objectNames = connectionInstance.describeGlobal().types;

                //string[] objectNames = new string[] { "Account", "Contact" };

                DescribeSObjectResult[] d = connectionInstance.describeSObjects(objectNames);

                foreach(string objectName in objectNames) {

                    SFObjectType st = new SFObjectType() { Name = objectName };

                    //Activator.CreateInstanceFrom("WCFLOBTalk.SalesForceWCF.SalesForceWCFAdapter.dll", d.name);

                    // if (d.name.Equals("Account")) { o = Activator.CreateInstance<Account>(); }

                    List<string> methods = new List<string>();

                    methods.Add("Create");
                    methods.Add("Delete");
                    methods.Add("Retrieve");
                    methods.Add("Undelete");
                    methods.Add("Update");

                    

                    // Remove any that don't make sense.

                    st.Methods = methods;
                    types.Add(st);
                }
                
                sfm.Types = types;
            }
            else
            {
                XmlSerializer x = new XmlSerializer(typeof(SFMetadata));
                StreamReader rd = new StreamReader(@"C:\Documents and Settings\Administrator\Desktop\SFnodes.xml");
                sfm = x.Deserialize(rd) as SFMetadata; 

            }
            // Populate other metadata types



            return sfm;
        }

        #region Results Converters

        public static SalesForceCallResponse WrapResponse(SaveResult r)
        {
            SalesForceCallResponse res = new SalesForceCallResponse();

            res.Success = r.success;
            res.Id = r.id;

            if (r.success == false)
            {
                if (r.errors.Length > 0)
                {
                    foreach (Error e in r.errors)
                    {
                        GenericError ge = new GenericError();
                        ge.Fields = e.fields;
                        ge.ErrorMessage = e.message;
                        ge.StatusCode = e.statusCode.ToString();
                    }
                }
            }

            return res;
        }

        public static SalesForceCallResponse WrapResponse(DeleteResult r)
        {
            SalesForceCallResponse res = new SalesForceCallResponse();

            res.Success = r.success;
            res.Id = r.id;

            if (r.success == false)
            {
                if (r.errors.Length > 0)
                {
                    foreach (Error e in r.errors)
                    {
                        GenericError ge = new GenericError();
                        ge.Fields = e.fields;
                        ge.ErrorMessage = e.message;
                        ge.StatusCode = e.statusCode.ToString();
                    }
                }
            }

            return res;
        }

        #endregion

    }
    [XmlRoot()]
    public class SFMetadata
    {
        [XmlArray(ElementName="Types")]
        public List<SFObjectType> Types = new List<SFObjectType>();

        public SFMetadata() { }

        public SFMetadata(List<SFObjectType> types)
        {
            Types = types;
        }
    }

    public class SFObjectType
    {
        [XmlElement()]
        public string Name { get; set; }
        [XmlArray(ElementName="Methods")]
        public List<string> Methods { get; set; }
        
    }

    public class SFMethods
    {
        public List<string> Methods = new List<string>();

    }

    // classes for any static service request/responses
    [XmlRoot()]
    public class SalesForceCallResponse
    {
        [XmlElement()]
        public string Id { get; set; }

        [XmlArray(ElementName="Errors")]
        public GenericError[] Errors { get; set; }

        [XmlElement()]
        public bool Success { get; set; }

    }

    public class GenericError
    {
        [XmlArray(ElementName="Fields")]
        public string[] Fields { get; set; }

        [XmlElement()] 
        public string ErrorMessage { get; set; }

        [XmlElement()]
        public string StatusCode { get; set; }
    }



}
